package cz.muni.fi.pa165.soap.client;

import cz.muni.fi.pa165.soap.CustomerDTO;
import cz.muni.fi.pa165.soap.EmployeeDTO;
import cz.muni.fi.pa165.soap.client.editPannel.EditCustomer;
import cz.muni.fi.pa165.soap.client.editPannel.EditEmployee;
import cz.muni.fi.pa165.soap.client.editPannel.OnSave;
import cz.muni.fi.pa165.soap.client.manager.CustomerManager;
import cz.muni.fi.pa165.soap.client.manager.EmployeeManager;
import cz.muni.fi.pa165.soap.client.table.Button;
import cz.muni.fi.pa165.soap.client.table.JTableButtonMouseListener;
import cz.muni.fi.pa165.soap.client.table.JTableButtonRenderer;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.List;
import java.util.ResourceBundle;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.table.TableCellRenderer;

/**
 *
 * @author shifty
 */
public class MainFrame extends JFrame{
    
    public static ResourceBundle RB;
    
    private List<CustomerDTO> customerDatabase;
    private List<EmployeeDTO> employeeDatabase;
    private JTable customers;
    private JTable employees;
    private EmployeeTableModel emps;
    private CustomerTableModel custs;
    private EmployeeManager em;
    private CustomerManager cm;
    private EditFrame editFrame;
    
    private boolean isInit=false;
    
    public MainFrame(ResourceBundle rb) {
        MainFrame.RB=rb;
        
        try {
            tryInit();
        } catch(Exception e) {
            showConnectionError();
        }
        init();
    }
    
    private void init() {
        setTitle("SOAP connector");
        setLayout(new BorderLayout());
        JTabbedPane tabPane = new JTabbedPane();
        JMenuBar menuBar = new JMenuBar();
        JMenu menu = new JMenu(MainFrame.RB.getString("menu.create"));
        
        JMenuItem menuItemEmployee = new JMenuItem(MainFrame.RB.getString("main.employee"));
        menuItemEmployee.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, ActionEvent.CTRL_MASK));
        menuItemEmployee.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                addNewEmployeeToEdit();
            }
        });
        JMenuItem menuItemCustomer = new JMenuItem(MainFrame.RB.getString("main.customer"));
        menuItemCustomer.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK));
        menuItemCustomer.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                addNewCustomerToEdit();
            }
        });
        menu.add(menuItemEmployee);
        menu.add(menuItemCustomer);
        JMenu menuMain = new JMenu(MainFrame.RB.getString("menu.menu"));
        JMenuItem menuItemRefresh = new JMenuItem(MainFrame.RB.getString("menu.refresh"));
        menuItemRefresh.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                refreshData();
            }
        });
        JMenuItem menuItemExit = new JMenuItem(MainFrame.RB.getString("menu.exit"));
        menuMain.add(menuItemRefresh);
        menuMain.add(menuItemExit);
        menuItemExit.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        menuBar.add(menuMain);
        menuBar.add(menu);
        add(menuBar,BorderLayout.NORTH);
        add(tabPane,BorderLayout.CENTER);
        
        emps = new EmployeeTableModel(getEmployeeColumnNames());
        emps.setActionListenerEdit(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Long id = ((Button)e.getSource()).getItemId();
                addEmployeeToEdit(id);
            }
        });
        emps.setActionListenerDelete(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Long id = ((Button)e.getSource()).getItemId(); 
                removeEmployee(id);
            }
        });
        employees = new JTable(emps);
        
        custs = new CustomerTableModel(getCustomerColumnNames());
        custs.setActionListenerEdit(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Long id = ((Button)e.getSource()).getItemId();
                addCustomerToEdit(id);
            }
        });
        custs.setActionListenerDelete(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Long id = ((Button)e.getSource()).getItemId();
                removeCustomer(id);
            }
        });
        customers = new JTable(custs);
        
        TableCellRenderer buttonRenderer1 = new JTableButtonRenderer();
        customers.getColumn(TableModel.EDIT_BUTTON).setCellRenderer(buttonRenderer1);
        customers.getColumn(TableModel.DELETE_BUTTON).setCellRenderer(buttonRenderer1);
        customers.addMouseListener(new JTableButtonMouseListener(customers));
              
        TableCellRenderer buttonRenderer = new JTableButtonRenderer();
        employees.getColumn(TableModel.EDIT_BUTTON).setCellRenderer(buttonRenderer);
        employees.getColumn(TableModel.DELETE_BUTTON).setCellRenderer(buttonRenderer);
        employees.addMouseListener(new JTableButtonMouseListener(employees));
        
        JPanel tab1 = new JPanel(new BorderLayout());
        JScrollPane scrollPanel1 = new JScrollPane(customers);
        tab1.add(scrollPanel1);
        JPanel tab2 = new JPanel(new BorderLayout());
        JScrollPane scrollPanel2 = new JScrollPane(employees);
        
        tab2.add(scrollPanel2);
        
        
        tabPane.add(RB.getString("main.customers"),tab1);
        tabPane.add(RB.getString("main.employees"),tab2);
        
        refreshData();
    }
    
    private void refreshData() {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    tryInit();
                    custs.setValuesFromList(cm.loadCustomers());
                    custs.fireTableDataChanged();
                    emps.setValuesFromList(em.loadEmployees());
                    emps.fireTableDataChanged();
                } catch(Exception e) {
                    showConnectionError();
                }
            }
        });
        
    }
    
    public String[] getEmployeeColumnNames() { 
        String[] columns = new String[]{
            RB.getString("table.id"),
            RB.getString("table.name"),
            RB.getString("table.birthDate"),
            RB.getString("table.password"),
            RB.getString("table.role"),
            RB.getString("table.edit"),
            RB.getString("table.delete")
        };
        return columns;
    }    
    public String[] getCustomerColumnNames() {
        String[] columns = new String[] {
            RB.getString("table.id"),
            RB.getString("table.name"),
            RB.getString("table.address"),
            RB.getString("table.city"),
            RB.getString("table.zip"),
            RB.getString("table.country"),
            RB.getString("table.accountNumber"),
            RB.getString("table.edit"),
            RB.getString("table.delete")
        };
        return columns;
    }
    
    
    public void addToEditFrame(final JPanel panel) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                if(editFrame == null) {
                    editFrame = new EditFrame(RB);
                    editFrame.addTab(panel);
                    editFrame.setSize(Client.WIDTH, Client.HEIGHT);
                    editFrame.setVisible(true);
                    editFrame.pack();
                } else {
                    editFrame.addTab(panel);
                }
            }
        });
    }
    
    public void addNewEmployeeToEdit() {
        EditEmployee ee = new EditEmployee(RB,null);
        ee.onSave(new OnSave<EmployeeDTO>() {
            @Override
            public void execute() {
                javax.swing.SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            tryInit();
                            em.createEmployee(getObject());
                        } catch(Exception e) {
                            showConnectionError();
                        }
                        refreshData();
                    }
                }); 
            }
        });
        addToEditFrame(ee);
    }
    
    public void addEmployeeToEdit(final Long id) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    tryInit();
                    EditEmployee ee = new EditEmployee(RB,em.getEmployeeById(id));
                    ee.onSave(new OnSave<EmployeeDTO>() {
                        @Override
                        public void execute() {
                            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                                @Override
                                public void run() {
                                    try {
                                        tryInit();
                                        em.updateEmployee(getObject());
                                    } catch(Exception e) {
                                        showConnectionError();
                                    }
                                    refreshData();
                                }
                            });     
                        }
                    });
                    addToEditFrame(ee);
                } catch (Exception e) {
                    showConnectionError();
                }
            }
        });
    }
    
    public void addNewCustomerToEdit() {
        EditCustomer ec = new EditCustomer(RB,null);
        ec.onSave(new OnSave<CustomerDTO>() {
            @Override
            public void execute() {
                javax.swing.SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            tryInit();
                            cm.createCustomer(getObject());
                        } catch(Exception e) {
                            showConnectionError();
                        }
                        refreshData();
                    }
                });    
            }
        });
        addToEditFrame(ec);
    }
    
    public void addCustomerToEdit(final Long id) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    tryInit();
                    EditCustomer ec = new EditCustomer(RB,cm.getCustomerById(id));
                    ec.onSave(new OnSave<CustomerDTO>() {
                        @Override
                        public void execute() {
                            javax.swing.SwingUtilities.invokeLater(new Runnable() {
                                @Override
                                public void run() {
                                    try {
                                        tryInit();
                                        cm.updateCustomer(getObject());
                                    } catch(Exception e) {
                                        showConnectionError();
                                    }
                                    refreshData();
                                }
                            });     
                        }
                    });
                    addToEditFrame(ec);    
                } catch (Exception e) {
                    showConnectionError();
                }
                
            }
        });
    }
    
    public void removeEmployee(final Long id) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    tryInit();
                    em.removeEmployee(id);
                    refreshData();
                } catch(javax.xml.ws.soap.SOAPFaultException e) {
                    showConstraintError();
                } catch(Exception e) {
                    showConnectionError();
                }
            }
        });
    }
    
    public void removeCustomer(final Long id) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    tryInit();
                    cm.removeCustomer(id);
                    refreshData();
                } catch(javax.xml.ws.soap.SOAPFaultException e) {
                    showConstraintError();
                } catch(Exception e) {
                    showConnectionError();
                }
            }
        });
    };
    
    public void showConnectionError() {
        JOptionPane.showMessageDialog(this,
            MainFrame.RB.getString("error.connection.info"),
            MainFrame.RB.getString("error.connection"),
            JOptionPane.WARNING_MESSAGE);
    }
    public void showConstraintError() {
        JOptionPane.showMessageDialog(this,
            MainFrame.RB.getString("error.constraint.info"),
            MainFrame.RB.getString("error.constraint"),
            JOptionPane.WARNING_MESSAGE);
    }
    
    private void tryInit() {
        if(em == null) {
            em = new EmployeeManager();
        }
        if(cm == null) {
            cm = new CustomerManager();
        }
    }
}
